import { readdirSync, renameSync, statSync } from 'fs'

/** 重命名规则方法 */
type RenameRole = (
  fileName: string,
  extName: string,
  filePath: string
) => Promise<{ fileName: string; extName: string } | void>

/** 重命名规则  */
const rules: Record<string, RenameRole> = {
  /** 时间戳文件名转时间 */
  timestamp(fileName, extName, filePath) {
    let isTS = /^(\d{13})$/.test(fileName)
    if (isTS) {
      fileName = getLocalDateStr(new Date(+fileName))
      return Promise.resolve({ fileName, extName })
    }
    return Promise.resolve()
  },

  // 最早时间
  minDate(fileName, extName, filePath) {
    // 文件名包含时间戳
    let tsReg = /^(\D*)(\d{13})$/g
    let ts = +(tsReg.test(fileName)
      ? fileName.replace(tsReg, '$2')
      : new Date())

    let fStat = statSync(filePath)
    let { atimeMs, birthtimeMs, ctimeMs, mtimeMs } = fStat

    // 获取最早时间
    let date = new Date(Math.min(atimeMs, birthtimeMs, ctimeMs, mtimeMs, ts))
    let dateStr = getLocalDateStr(date)
    return Promise.resolve({ fileName: dateStr, extName })
  }
}

// 获取本地时间字符串
function getLocalDateStr(date: Date) {
  date.setHours(date.getHours() - date.getTimezoneOffset() / 60)
  return date
    .toJSON()
    .replace(/[:]/g, '-')
    .replace('T', ' ')
    .replace(/\.\S{4}$/, '')
}

/**
 * 目录文件重命名
 * @param {String} directory 目录
 * @param {Function | String} rule 规则
 * @param {Boolean} preview 是否预览，否则将开始重命名
 */
export default async function (
  directory: string,
  rule: RenameRole | keyof typeof rules,
  preview = true
) {
  // 根目录
  const basePath = directory + '/'

  const ruleFn = typeof rule === 'string' ? rules[rule] : rule

  console.log()
  console.log(`开始批量重命名目录: ${basePath}`)
  console.log()

  const files = await readdirSync(directory)

  console.log(files)

  files.forEach(async function (file) {
    const filePath = basePath + file

    // 原文件名
    const [, fileName, , extName] = /^(.*)(\.([^.]+))$/.exec(file) as string[]

    const formatFile = await ruleFn(fileName, extName, filePath)

    if (formatFile) {
      // 新文件名
      let { fileName: newFileName, extName: newExtName } = formatFile
      let newName = newFileName + (newExtName ? '.' + newExtName : '')

      console.log(`${file} => ${newName}`)

      if (preview) return

      await renameSync(filePath, basePath + newName)

      console.log(`${file} => ${newName}  成功!`)
    }
  })
}
